import ply.lex as lex 
import ErrorLexico
import VarGlobales

class Lexer(object):
    def __init__(self):
        self.lexer = lex.lex(object = self)

    def GetTokens(self):
        return self.tokens
            
    def input(self, text):
        self.lexer.input(text)
        
    def token(self):
        return self.lexer.token()
    
    tokens = (
              'avanzar',
              'av',
              'retroceder',
              'rt',
              'alto',
              'al',
              'bajarpluma',
              'bp',
              'subirpluma',
              'sp',
              'girarderecha',
              'gd',
              'girarizquierda',
              'gi',
              'borrarpantalla',
              'bo',
              'procedimiento',
              'pr',
              'inicio',
              'fin',
              'si',
              'sino',
              'repetir',
              'mientras',
              'escribe',
              'para',
              'retorno',
              'incremento',
              'hasta',
              'y',
              'o',
              'falso',
              'verdadero',
              'NUMEROENTERO',
              'NUMEROFLOTANTE',
              'ID',
              'IGUAL',
              'MAYOROIGUAL',
              'MENOROIGUAL',
              'DIFERENTE'
              )
    
    
    literals = ('+','-','*','/','(',')','=','!','>','<',',')
    
    t_MAYOROIGUAL = r'\>=' 
    t_MENOROIGUAL = r'\<='
    t_IGUAL = r'\=='
    t_DIFERENTE = r'\!='     
    
    def t_cometarios(self, token):
        r'\#[\w\W]*?\#'
        #self.lexer.lineno += len(token.value)
        self.lexer.lineno += token.value.count('\n')
        pass
    
    def t_comentario_malformado(self,token):
        r'\#[\w\W]*?(?<!\#)|\#'
        aux = "Linea %d: Comentario malformado"%((0 if token.lineno - VarGlobales.Lresta < 0 else token.lineno - VarGlobales.Lresta))
        raise ErrorLexico.ErrorLexico(aux)
    
    def t_identificador_malformado(self,token):  
        r'([a-zA-Z_]\w*(\.\w*)+|\d+\.\d+[a-zA-Z_]\w*|[a-zA-Z_]\w*\.|\.[a-zA-Z_]\w*|\d+[a-zA-Z_]\w*)|_\w*'
        aux = "Linea %d: %s Identificador malformado"%((0 if token.lineno - VarGlobales.Lresta < 0 else token.lineno - VarGlobales.Lresta), token.value)
        raise ErrorLexico.ErrorLexico(aux)
    
    def t_NUMEROFLOTANTE(self, token):
        r'((0|[1-9]+)\.[0-9]+)|([1-9][0-9]+\.[0-9]+)'
        numero = float(token.value)
        if numero > 1048576:
            aux="Linea %d: %s Numero fuera de rango"%((0 if token.lineno - VarGlobales.Lresta < 0 else token.lineno - VarGlobales.Lresta), token.value)
            raise ErrorLexico.ErrorLexico(aux)
        token.value = numero 
        return token
    
    def t_numero_malformado(self,token):
        r'((0+|[1-9]+)\.)|(\.([0-9]+))|0+[0-9]+'
        aux="Linea %d: %s Numero malformado"%((0 if token.lineno - VarGlobales.Lresta < 0 else token.lineno - VarGlobales.Lresta), token.value)
        raise ErrorLexico.ErrorLexico(aux)

    def t_NUMEROENTERO(self, token):
        r'0(?!\d)|([1-9]\d*)' 
        numero = int(token.value)
        if numero > 1048576:
            aux="Linea %d: %s Numero fuera de rango"%((0 if token.lineno - VarGlobales.Lresta < 0 else token.lineno - VarGlobales.Lresta), token.value)
            raise ErrorLexico.ErrorLexico(aux)
        token.value = numero 
        return token
    
    
    
    def t_ID(self,token):  
        r'[A-Za-z][\w]*'
        for palabra in Lexer.tokens[0:33]:
            if token.value == palabra.lower():
                token.type = palabra
        return token
    
    def t_Newline(self,token):
        r'\n+'
        self.lexer.lineno += len(token.value)
    
    def t_error(self,token):
        token.lexer.skip(1)
        aux="Linea %d: %s Caracter no valido"%((0 if token.lineno - VarGlobales.Lresta < 0 else token.lineno - VarGlobales.Lresta), token.value[0])
        raise ErrorLexico.ErrorLexico(aux)
        
    t_ignore = ' \t\r'
    
#l=Lexer()
#l.input(">= 1212 y o 1212 32.2 3  2123.232  212 112 sd 3232 falso")
#
#while 1:
#    aux=l.token()
#    if aux==None:break
#    print aux
    